#version 0.1

#basic code of the pefile stuff is more or less derived from their tutorial on the goggle code page.
#same goes for peid signature stuff and yara, basically i read the tutorial for everythin you see here and am applying it to my code
#todo
#pefile - https://code.google.com/p/pefile/downloads/detail?name=pefile-1.2.10-139.zip&can=2&q= (run python setup.py install in cwd)
#peid - https://reverse-engineering-scripts.googlecode.com/files/UserDB.TXT (place in cwd)
#yara - https://googledrive.com/host/0BznOMqZ9f3VUek8yN3VvSGdhRFU/yara-2.1.0-win32.zip (place in cwd) https://googledrive.com/host/0BznOMqZ9f3VUek8yN3VvSGdhRFU/yara-python-2.1.0.win32-py2.7.exe
#file magic - NOT IMPLEMENTED https://github.com/ahupp/python-magic/archive/master.zip (run python setup.py install in cwd, if you don't have setuptools, open setup.py and comment line1, uncomment line 2) http://cygwin.com/setup-x86.exe install cygwin and add C:\cygwin\bin to $PATH 
#ssdeep
#virustotal - https://www.virustotal.com/en/documentation/public-api/ can send multiple requests for rescan at once (should use the 4 per minute limit and a timer
#unpack
#unzip
#directory recursion

#!/usr/bin/python

import pefile, peutils, sys, re, hashlib, yara, magic, os

def gethash(filecontent, fileout):
    #hashing
    fileout.write('MD5 Hash:    {}\n'.format(hashlib.md5(filecontent).hexdigest()))
    fileout.write('SHA1 Hash:   {}\n'.format(hashlib.sha1(filecontent).hexdigest()))
    fileout.write('SHA256 Hash: {}\n'.format(hashlib.sha256(filecontent).hexdigest()))
     

def listPEInfo(pe, fileout):
    #basic PE info
    fileout.write('\nBasic PE Info:\n')
    fileout.write('Entry Point: {}\n'.format(hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)))
    fileout.write('Image Base:  {}\n'.format(hex(pe.OPTIONAL_HEADER.ImageBase)))
    fileout.write('Import Hash: {}\n'.format(pe.get_imphash()))  
    
    #peid file matches
    signatures = peutils.SignatureDatabase('UserDB.TXT')
    matches = signatures.match_all(pe, ep_only = True)
    fileout.write('PeID Matches:\n')
    if matches==None:
        fileout.write('  None\n')
    else:
        for match in matches:
            fileout.write('  {}\n'.format(match))
    return
    
def listyara(file, fileout):
    #yara
    rules = yara.compile('yara/index_binary.yar')
    matches = rules.match(file)
    fileout.write('Yara Matches:\n')
    if matches==[]:
        fileout.write('  None\n')
    else:
        for match in matches:
            fileout.write('  {}\n'.format(match)) 
    return
    
def listSectionInfo(pe, fileout):
    #Section Info
    fileout.write('\nNumber of Sections: {}\n'.format(pe.FILE_HEADER.NumberOfSections))
    fileout.write('  {0:15s} {1:15s} {2:13s} {3}\n'.format('Section Name', 'Virtual Address', 'Virtual Size', 'Raw Size'))

    for section in pe.sections:
      fileout.write('  {0:15s} {1:15s} {2:13s} {3}\n'.format(section.Name.strip('\0'), hex(section.VirtualAddress), hex(section.Misc_VirtualSize), hex(section.SizeOfRawData)))

    return
    
def listimports(pe, fileout):
    #imports
    pe.parse_data_directories()
    fileout.write('\nImports:')
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
      fileout.write('\n{}\n'.format(entry.dll))
      fileout.write('  {0:11s} {1}\n'.format('Address', 'Name'))
      for imp in entry.imports:
        fileout.write('  {0:11s} {1}\n'.format(hex(imp.address), imp.name))
    return
    
def listexports(pe, fileout):   
    #exports    
    if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
        fileout.write('\nExports:')
        fileout.write('  {0:11s} {1:7s} {2}\n'.format('Address', 'Ordinal', 'Name'))   
        for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
            fileout.write('  {0:11s} {1:7s} {2}\n'.format(hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), str(exp.ordinal), exp.name))
    return

def liststrings(filecontent, fileout):
#need a way of keeping from getting repeats, maybe with a regex? 
#RFC 3986 legal characters in url: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=.
#i might stick with more common ones...
    fileout.write('\nNetwork Strings:\n') 
    somestrings = []
    somestrings = re.findall(r'http[A-Za-z0-9-_:/&=.%]+', filecontent, re.IGNORECASE) #url starting with http
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'www.[A-Za-z0-9-_:/&=.%]+', filecontent, re.IGNORECASE) #url starting with www
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.com[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with com TLD
    for string in somestrings:
        fileout.write('{}\n'.format(string))        
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.org[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with org TLD
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'[A-Za-z0-9/_:.%]+\.biz[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with biz TLD
    for string in somestrings:
        fileout.write('{}\n'.format(string))           
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.ru[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with ru TLD russian
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.su[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with su TLD soviet union
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.cn[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with cn TLD china
    for string in somestrings:
        fileout.write('{}\n'.format(string))        
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.info[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with info TLD
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+\.net[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with net TLD
    for string in somestrings:
        fileout.write('{}\n'.format(string))
#    somestrings = re.findall(r'[A-Za-z0-9-_:/&=.%]+.exe[A-Za-z0-9-_:/&=.%]*', filecontent, re.IGNORECASE) #url with exe in path, tends to also grab
#    for string in somestrings:
#        fileout.write('{}\n'.format(string))


    fileout.write('\nFile System Strings:\n') 
    somestrings = re.findall(r'[A-Za-z0-9\\_:.% ]+\.exe', filecontent, re.IGNORECASE) #file path ending in .exe
    for string in somestrings:
        fileout.write('{}\n'.format(string))        
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.dll', filecontent, re.IGNORECASE) #file path ending in .dll
    for string in somestrings:
        fileout.write('{}\n'.format(string))
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.sys', filecontent, re.IGNORECASE) #file path ending in .sys
    for string in somestrings:
        fileout.write('{}\n'.format(string))          
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.bat', filecontent, re.IGNORECASE) #file path ending in .bat
    for string in somestrings:
        fileout.write('{}\n'.format(string))
#    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.com', filecontent, re.IGNORECASE) #file path ending in .com
#    for string in somestrings:
#        fileout.write('{}\n'.format(string))  
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.vbs', filecontent, re.IGNORECASE) #file path ending in .vbs
    for string in somestrings:
        fileout.write('{}\n'.format(string))  
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.zip', filecontent, re.IGNORECASE) #file path ending in .zip
    for string in somestrings:
        fileout.write('{}\n'.format(string))  
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.rar', filecontent, re.IGNORECASE) #file path ending in .rar
    for string in somestrings:
        fileout.write('{}\n'.format(string))  
    somestrings = re.findall(r'[A-Za-z0-9\_:.% ]+\.cab', filecontent, re.IGNORECASE) #file path ending in .cab
    for string in somestrings:
        fileout.write('{}\n'.format(string))  
          
    fileout.write('\nRegistry Strings:\n') 
    somestrings = re.findall(r'HKLM\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKLM
    for string in somestrings:
        fileout.write('{}\n'.format(string))    
    somestrings = re.findall(r'HKCU\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKCU
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
    somestrings = re.findall(r'HKCR\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKCR
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
    somestrings = re.findall(r'HKU\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKU
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
    somestrings = re.findall(r'HKCC\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKCC
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
    somestrings = re.findall(r'HKEY_LOCAL_MACHINE\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKEY_LOCAL_MACHINE
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
    somestrings = re.findall(r'HKEY_CURRENT_USER\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKEY_CURRENT_USER
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
    somestrings = re.findall(r'HKEY_CLASSES_ROOT\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKEY_CLASSES_ROOT
    for string in somestrings:
        fileout.write('{}\n'.format(string))    
    somestrings = re.findall(r'HKEY_USERS\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKEY_USERS
    for string in somestrings:
        fileout.write('{}\n'.format(string))         
    somestrings = re.findall(r'HKEY_CURRENT_CONFIG\\[A-Za-z0-9\\_:.% ]+', filecontent, re.IGNORECASE) #reg key starting with HKEY_CURRENT_CONFIG
    for string in somestrings:
        fileout.write('{}\n'.format(string)) 
        
    fileout.write('\nAll Strings:\n')
    allstrings = []
    allstrings = re.findall('[A-Za-z0-9!@#$%^&*()-=_+\[\]\\{\}|;\':",.<>?`~ ]{2,}', filecontent)   
    for string in allstrings:
        fileout.write('{}\n'.format(string))
    return
 
 
 
def main():
    #do i have a file to open
    try: 
        file = sys.argv[1]   
    except:
        print 'Usage: filedata.py filename' 
        exit()
    
    #the file and outputfile
    filehandle = open(file, 'rb')
    filecontent = filehandle.read()
    fileout = open(file + '.txt', 'w')
    
    #stuff for all files
    fileout.write('File Name:   {}\n'.format(file))
    fileout.write('File Size:   {}\n'.format(os.path.getsize(file))) 
    
    gethash(filecontent, fileout)
    listyara(file, fileout)

    
    
#doesn't work, will TS later    
#    i = magic.from_file(file)
#    print(i)
    
    #are you a pe file
    nope=0
    try:
        pe =  pefile.PE(file)
    except:
        nope=1
        pass
    if nope==0:    
        listPEInfo(pe, fileout)
        listSectionInfo(pe, fileout)
        listimports(pe, fileout)
        listexports(pe, fileout)
    #finally    
    liststrings(filecontent, fileout)       
    filehandle.close()
    fileout.close()
    return

if __name__ == '__main__':
    main()